<!DOCTYPE html>
<html>
<head>
    <title>PlayCanvas First Person Camera</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link rel="icon" type="image/png" href="../playcanvas-favicon.png" />
    <script src="../../build/output/playcanvas.js"></script>
    <script src="../wasm-loader.js"></script>
    <style>
        body { 
            margin: 0;
            overflow-y: hidden;
        }
    </style>
</head>

<body>
    <!-- The canvas element -->
    <canvas id="application-canvas"></canvas>

    <!-- The script -->
    <script>
        if (wasmSupported()) {
            loadWasmModuleAsync('Ammo', '../lib/ammo/ammo.wasm.js', '../lib/ammo/ammo.wasm.wasm', demo);
        } else {
            loadWasmModuleAsync('Ammo', '../lib/ammo/ammo.js', '', demo);
        }

        function demo() {
            var canvas = document.getElementById("application-canvas");

            // Create the app and start the update loop
            var app = new pc.Application(canvas, {
                mouse: new pc.Mouse(document.body),
                touch: new pc.TouchDevice(document.body)
            });
            app.start();

            // Set the canvas to fill the window and automatically change
            // resolution to be the same as the canvas size
            app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
            app.setCanvasResolution(pc.RESOLUTION_AUTO);

            window.addEventListener("resize", function () {
                app.resizeCanvas(canvas.width, canvas.height);
            });

            // A list of assets that need to be loaded
            var assetManifest = [
                {
                    type: "model",
                    url: "../assets/models/statue/statue.json"
                },
                {
                    type: "script",
                    url: "../assets/scripts/camera/first-person-camera.js"
                }
            ];

            // Load all assets and then run the example
            var assetsToLoad = assetManifest.length;
            assetManifest.forEach(function (entry) {
                app.assets.loadFromUrl(entry.url, entry.type, function (err, asset) {
                    if (!err && asset) {
                        assetsToLoad--;
                        entry.asset = asset;
                        if (assetsToLoad === 0) {
                            run();
                        }
                    }
                });
            });

            function run() {
                // Create a physical floor
                var floor = new pc.Entity();
                floor.addComponent("collision", {
                    type: "box",
                    halfExtents: new pc.Vec3(100, 0.5, 100)
                });
                floor.addComponent("rigidbody", {
                    type: "static",
                    restitution: 0.5
                });
                floor.setLocalPosition(0, -0.5, 0);
                app.root.addChild(floor);

                var floorModel = new pc.Entity();
                floorModel.addComponent("model", {
                    type: "plane"
                });
                floorModel.setLocalPosition(0, 0.5, 0);
                floorModel.setLocalScale(200, 1, 200);
                floor.addChild(floorModel);

                // Create a model entity and assign the statue model
                var model = new pc.Entity();
                model.addComponent("collision", {
                    type: "mesh",
                    asset: assetManifest[0].asset
                });
                model.addComponent("model", {
                    type: "asset",
                    asset: assetManifest[0].asset
                });
                model.addComponent("rigidbody", {
                    type: "static",
                    restitution: 0.5
                });
                app.root.addChild(model);

                // Create a camera that will be driven by the character controller
                var camera = new pc.Entity();
                camera.addComponent("camera", {
                    clearColor: new pc.Color(0.4, 0.45, 0.5),
                    farClip: 100,
                    fov: 65,
                    nearClip: 0.1
                });
                camera.setLocalPosition(0, 1, 0);

                // Create a physical character controller
                var characterController = new pc.Entity();
                characterController.addComponent("collision", {
                    axis: 0,
                    height: 2,
                    radius: 0.5,
                    type: "capsule"
                });
                characterController.addComponent("rigidbody", {
                    angularDamping: 0,
                    angularFactor: pc.Vec3.ZERO,
                    friction: 0.3,
                    linearDamping: 0,
                    linearFactor: pc.Vec3.ONE,
                    mass: 80,
                    restitution: 0,
                    type: "dynamic"
                });
                characterController.addComponent("script");
                characterController.script.create("characterController");
                characterController.script.create("firstPersonCamera", {
                    attributes: {
                        camera: camera
                    }
                });
                characterController.script.create("gamePadInput");
                characterController.script.create("keyboardInput");
                characterController.script.create("mouseInput");
                characterController.script.create("touchInput");
                characterController.setLocalPosition(0, 1, 10);

                // Add the character controll and camera to the hierarchy
                app.root.addChild(characterController);
                characterController.addChild(camera);

                // Create a directional light
                var light = new pc.Entity();
                light.addComponent("light", {
                    castShadows: true,
                    color: new pc.Color(1, 1, 1),
                    normalOffsetBias: 0.05,
                    shadowBias: 0.2,
                    shadowDistance: 16,
                    type: "directional",
                    shadowResolution: 2048
                });
                app.root.addChild(light);
                light.setLocalEulerAngles(45, 30, 0);
            }
        }
    </script>
</body>
</html>
